package com.event.core.parse;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.event.common.constant.CommonConstant;
import com.event.common.constant.KeyTag;
import com.event.common.model.EventCacheKey;
import com.event.common.model.MethodAnnotationEvent;
import com.event.common.util.KeyParserUtil;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/*
 * @description 默认解析器
 * @author Bing
 * @date 2024/10/8 14:07
 **/
@Component
public class DefaultCacheableParse extends CacheableParse{
    /**
     * spel表达式解析器
     */
    private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();;
    /**
     * <别名,缓存key列表>
     */
    private Map<String,List<EventCacheKey>> aliasCacheKeyMap = new ConcurrentHashMap<>();
    /**
     * 缓存key列表
     */
    private Map<String,EventCacheKey> cacheKeyMap = new ConcurrentHashMap<>();

    @Override
    public void parse() {
        // 获取Cacheable方法注解事件
        List<MethodAnnotationEvent> cacheableEvents = this.getCacheableEvents();
        if(CollUtil.isEmpty(cacheableEvents)){
            return;
        }
        List<EventCacheKey> cacheKeys = new ArrayList<>();
        for(MethodAnnotationEvent cacheableEvent : cacheableEvents){
            Cacheable cacheable = (Cacheable) cacheableEvent.getAnnotation();
            if(StrUtil.isBlank(cacheable.key())){
                continue;
            }
            if(ObjectUtil.isNull(cacheable.cacheNames())){
                continue;
            }
            // 组装缓存key
            Arrays.stream(cacheable.cacheNames()).forEach(cacheName -> {
                Expression expression = spelExpressionParser.parseExpression(cacheable.key());
                String cacheKey = cacheName+ KeyTag.CACHENAME_TAG+ expression.getValue();
                EventCacheKey eventCacheKey = KeyParserUtil.getCacheKey(cacheKey);
                if(ObjectUtil.isNotNull(eventCacheKey)){
                    if(StrUtil.isNotBlank(eventCacheKey.getBusIdName())){
                        eventCacheKey.setBusIdName(CommonConstant.DEFAULT_BUSID_NAME);
                    }
                   cacheKeys.add(eventCacheKey);
               }
            });
        }
        if(CollUtil.isEmpty(cacheKeys)){
            return;
        }
        // 根据别名分组
        aliasCacheKeyMap = cacheKeys.stream().collect(Collectors.groupingBy(
                EventCacheKey::getNamespaceAlias,
                Collectors.mapping(
                        event -> event,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                CopyOnWriteArrayList::new
                        )
                )
        ));
    }

    @Override
    public Map<String,List<EventCacheKey>> getCacheKeys() {
        return aliasCacheKeyMap;
    }

    @Override
    public void addCacheKey(EventCacheKey eventCacheKey) {
        String registerKey = KeyParserUtil.getRegisterKey(eventCacheKey);
        EventCacheKey old = cacheKeyMap.putIfAbsent(registerKey,eventCacheKey);
        if(ObjectUtil.isNull(old)){
            aliasCacheKeyMap.computeIfAbsent(eventCacheKey.getNamespaceAlias(), k -> new CopyOnWriteArrayList<>()).add(eventCacheKey);
        }
    }

    @Override
    public String parse(EventCacheKey eventCacheKey) {
        return KeyParserUtil.getCacheKey(eventCacheKey);
    }
}
